﻿using System;
using System.Linq;
using System.Collections.Generic;

using log4net;

namespace SimbaRGVMonitor.Common.Diagnostics
{
    public sealed class MonitorLogger
    {
        internal MonitorLogger(string name, ILog logger)
        {
            this.name = name;
            this.logger = logger;
        }

        //====================================================================================================
        //以上是类型字段
        //----------------------------------------------------------------------------------------------------
        //以下是类型属性
        //====================================================================================================

        private readonly string name;
        private readonly ILog logger;
        private readonly object syncThreadLock = new object();

        //====================================================================================================
        //以上是类型字段
        //----------------------------------------------------------------------------------------------------
        //以下是类型属性
        //====================================================================================================

        public bool Enable
        {
            get;
            internal set;
        }

        public string Name
        {
            get { return name; }
        }

        //====================================================================================================
        //以上是类型属性
        //----------------------------------------------------------------------------------------------------
        //以下是类型事件及触发函数
        //====================================================================================================

        public event EventHandler<MonitorLoggerWritedEventArgs> LogWrited;
        private void OnLogWrited(DateTime writeTime, LogLevel writeLevel, string writeMessage)
        {
            var e = new MonitorLoggerWritedEventArgs(name, writeTime, writeLevel, writeMessage);
            LogWrited.TriggerEvent(this, e);
        }

        //====================================================================================================
        //以上是类型事件及触发函数
        //----------------------------------------------------------------------------------------------------
        //以下是记录日志
        //====================================================================================================
        
        public void Debug(Exception ex)
        {
            const LogLevel level = LogLevel.DEBUG;
            Write(level, ex);
        }

        public void Info(Exception ex)
        {
            const LogLevel level = LogLevel.INFO;
            Write(level, ex);
        }

        public void Warn(Exception ex)
        {
            const LogLevel level = LogLevel.WARN;
            Write(level, ex);
        }

        public void Error(Exception ex)
        {
            const LogLevel level = LogLevel.ERROR;
            Write(level, ex);
        }

        public void Fatal(Exception ex)
        {
            const LogLevel level = LogLevel.FATAL;
            Write(level, ex);
        }

        public void Write(LogLevel level, Exception ex)
        {
            var title = string.Format("{0}发生异常", name);
            Write(title, level, ex);
        }

        public void Debug(string title, Exception ex)
        {
            const LogLevel level = LogLevel.DEBUG;
            Write(title, level, ex);
        }

        public void Info(string title, Exception ex)
        {
            const LogLevel level = LogLevel.INFO;
            Write(title, level, ex);
        }

        public void Warn(string title, Exception ex)
        {
            const LogLevel level = LogLevel.WARN;
            Write(title, level, ex);
        }

        public void Error(string title, Exception ex)
        {
            const LogLevel level = LogLevel.ERROR;
            Write(title, level, ex);
        }

        public void Fatal(string title, Exception ex)
        {
            const LogLevel level = LogLevel.FATAL;
            Write(title, level, ex);
        }

        public void Write(string title, LogLevel level, Exception ex)
        {
            var errorMessage = CreateErrorMessage(title, ex);
            Write(level, errorMessage);
        }

        public void Debug(string text)
        {
            const LogLevel level = LogLevel.DEBUG;
            Write(level, text);
        }

        public void Info(string text)
        {
            const LogLevel level = LogLevel.DEBUG;
            Write(level, text);
        }

        public void Warn(string text)
        {
            const LogLevel level = LogLevel.WARN;
            Write(level, text);
        }

        public void Error(string text)
        {
            const LogLevel level = LogLevel.ERROR;
            Write(level, text);
        }

        public void Fatal(string text)
        {
            const LogLevel level = LogLevel.FATAL;
            Write(level, text);
        }

        public void Write(LogLevel level, string text)
        {
            DateTime currentTime;
            lock (syncThreadLock)
            {
                currentTime = DateTime.Now;
                if(Enable)
                {
                    WriteCore(text, level);
                }
            }
            OnLogWrited(currentTime, level, text);
        }

        private void WriteCore(string message, LogLevel level)
        {
            try
            {
                switch(level)
                {
                    case LogLevel.DEBUG:
                        logger.Debug(message);
                        break;
                    case LogLevel.INFO:
                        logger.Info(message);
                        break;
                    case LogLevel.WARN:
                        logger.Warn(message);
                        break;
                    case LogLevel.ERROR:
                        logger.Error(message);
                        break;
                    case LogLevel.FATAL:
                        logger.Fatal(message);
                        break;
                    default:
                        break;
                }
            }
            catch
            {
                //忽略所有记日志异常
            }
        }

        //====================================================================================================
        //以上是记录日志
        //----------------------------------------------------------------------------------------------------
        //以下是创建错误消息
        //====================================================================================================

        private static string CreateErrorMessage(string title, Exception ex)
        {
            var messages = ExceptionTrace.GetExceptionMessages(title, ex);
            return CreateBugMessage(messages);
        }

        private static string CreateBugMessage(params StackTraceMessage[] messages)
        {
            return messages
                .Select(message => string.Format("【{0}】\r\n{1}", message.Title, message.StackTrace))
                .ConcatText("\r\n");
        }
    }
}
